#include "guimanager.h"
#include "../common.h"

initialiseSingleton(GuiManager);

GuiManager::GuiManager()
    : mCurSelectedBaseNode(NULL)
{

}

GuiManager::~GuiManager()
{
    deleteAllNodes();
}

/// 删除所有的控件
void GuiManager::deleteAllNodes(void)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        delete (*iter).second;
        (*iter).second = NULL;
    }

    mBaseNodes.clear();
    mCurSelectedBaseNode = NULL;
}

/// 检测指定ID的控件是否在系统中
GuiBaseNode* GuiManager::getBaseNodeByID(int id)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.find(id);
    if(iter == mBaseNodes.end())
        return NULL;

    return (*iter).second;
}

/// 解析Json
void GuiManager::parsingJson(cJSON *routecondi)
{
    if(routecondi == NULL) return;

    // 遍历数组中的每个对象
    cJSON* item = NULL;
    cJSON_ArrayForEach(item, routecondi)
    {
        wxString nodetypeStr,nameStr,rectStr,tipStr,normalcolorStr,
            overcolorStr,clickcolorStr,bordercolorStr;
        int nodeid=0;

        wxCSConv gb2312Conv(wxFONTENCODING_UTF8);
        cJSON* nodetype = cJSON_GetObjectItem(item, "nodetype");
        if (nodetype && cJSON_IsString(nodetype)) {            
            nodetypeStr = wxString(nodetype->valuestring,gb2312Conv);
        }

        cJSON* id = cJSON_GetObjectItem(item, "id");
        if (id && cJSON_IsNumber(id)) {
            nodeid = id->valueint;
        }

        cJSON* name = cJSON_GetObjectItem(item, "name");
        if (name && cJSON_IsString(name)) {
            nameStr = wxString(name->valuestring,gb2312Conv);
        }

        cJSON* rect = cJSON_GetObjectItem(item, "rect");
        if (rect && cJSON_IsString(rect)) {
            rectStr = rect->valuestring;
        }

        cJSON* tip = cJSON_GetObjectItem(item, "tip");
        if (tip && cJSON_IsString(tip)) {
            tipStr = wxString(tip->valuestring,gb2312Conv);
        }

        cJSON* normalcolor = cJSON_GetObjectItem(item, "normalcolor");
        if (normalcolor && cJSON_IsString(normalcolor)) {
            normalcolorStr = normalcolor->valuestring;
        }

        cJSON* overcolor = cJSON_GetObjectItem(item, "overcolor");
        if (overcolor && cJSON_IsString(overcolor)) {
            overcolorStr = overcolor->valuestring;
        }

        cJSON* clickcolor = cJSON_GetObjectItem(item, "clickcolor");
        if (clickcolor && cJSON_IsString(clickcolor)) {
            clickcolorStr = clickcolor->valuestring;
        }

        cJSON* bordercolor = cJSON_GetObjectItem(item, "bordercolor");
        if (bordercolor && cJSON_IsString(bordercolor)) {
            bordercolorStr = bordercolor->valuestring;
        }

        if(nodetypeStr == wxT("按钮"))
        {
            GuiButton *decButton = this->addButton(nodeid,
                                                   nameStr,
                                                   ConvertStringToRect(rectStr));
            if(decButton)
            {
                decButton->setTipText(tipStr);
                decButton->setColor(ConvertStringToColour(normalcolorStr),
                                    ConvertStringToColour(overcolorStr),
                                    ConvertStringToColour(clickcolorStr));
                decButton->setBorderColor(ConvertStringToColour(bordercolorStr));
            }
        }
    }
}

wxRect GuiManager::ConvertStringToRect(wxString str)
{
    wxRect noderect;
    wxArrayString rectArray = SplitString(str,",");
    if(rectArray.size() == 4)
    {
        int x,y,w,h;
        rectArray[0].ToInt(&x);
        rectArray[1].ToInt(&y);
        rectArray[2].ToInt(&w);
        rectArray[3].ToInt(&h);

        noderect = wxRect(x,y,w,h);
    }

    return noderect;
}

wxColour GuiManager::ConvertStringToColour(wxString str)
{
    wxColour deccolour;
    wxArrayString rectArray = SplitString(str,",");
    if(rectArray.size() == 4)
    {
        int r,g,b,a;
        rectArray[0].ToInt(&r);
        rectArray[1].ToInt(&g);
        rectArray[2].ToInt(&b);
        rectArray[3].ToInt(&a);

        deccolour = wxColour(r,g,b,a);
    }

    return deccolour;
}

/// 删除指定ID的控件
bool GuiManager::deleteBaseNodeByID(int id)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.find(id);
    if(iter != mBaseNodes.end())
    {
        delete (*iter).second;
        (*iter).second = NULL;

        mBaseNodes.erase(iter);

        return true;
    }

    return false;
}

/// 更改指定ID的控件的ID
bool GuiManager::updateBaseNodeID(int oldId,int newId)
{
    if(oldId == newId)
        return false;

    GuiBaseNode *poldGuiBaseNode = this->getBaseNodeByID(oldId);
    GuiBaseNode *pnewGuiBaseNode = this->getBaseNodeByID(newId);

    if(poldGuiBaseNode == NULL || pnewGuiBaseNode != NULL)
        return false;

    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.find(oldId);
    if(iter != mBaseNodes.end())
        mBaseNodes.erase(iter);

    mBaseNodes[newId] = poldGuiBaseNode;
    poldGuiBaseNode->setID(newId);

    return true;
}

/// 添加一个按钮到系统中
GuiButton* GuiManager::addButton(int id,wxString btnName,wxRect rect)
{
    if(id < 0 || btnName == "" || rect.IsEmpty())
        return NULL;

    GuiBaseNode* decBaseNode = this->getBaseNodeByID(id);
    if(decBaseNode != NULL)
        return static_cast<GuiButton*>(decBaseNode);

    //std::lock_guard<std::mutex> lock(mNodeMutex);

    GuiButton *decBtn = new GuiButton(id,btnName);
    decBtn->setNodeType(GuiNodeType::GUINODETYPE_BUTTON);
    decBtn->setRect(rect);

    mBaseNodes[id] = decBtn;

    return decBtn;
}

/// 工作区域改变
void GuiManager::changeWorkingRect(wxRect workingrect)
{

}

/// 更新
void GuiManager::update(void)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        (*iter).second->update();
    }
}

/// 绘制
void GuiManager::draw(maindrawscene *painter)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        (*iter).second->draw(painter);
    }
}

/// 重置所有的控件
void GuiManager::resetAllNodes(void)
{
   // std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        if((*iter).second->getNodeType() == GuiNodeType::GUINODETYPE_BUTTON)
        {
            GuiButton *pbtn = static_cast<GuiButton*>((*iter).second);
            if(pbtn != NULL && pbtn->isSelected())
            {
                pbtn->setSelected(false);
                pbtn->setShowColor(pbtn->getNormalColor());
            }
        }
    }

    mCurSelectedBaseNode = NULL;
}

/// 处理鼠标事件
GuiBaseNode* GuiManager::OnMMouseEvent(wxMouseEvent event)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);
    bool isBtnClicked = false;

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        if((*iter).second->OnMMouseEvent(event))
        {
            mCurSelectedBaseNode = (*iter).second;
            isBtnClicked = true;
        }
        else
        {
            if((*iter).second->getNodeType() == GuiNodeType::GUINODETYPE_BUTTON &&
                mCurSelectedBaseNode != (*iter).second)
            {
                GuiButton *pbtn = static_cast<GuiButton*>((*iter).second);
                if(pbtn != NULL && pbtn->isSelected())
                {
                    pbtn->setSelected(false);
                    pbtn->setShowColor(pbtn->getNormalColor());
                }
            }
        }
    }

    return isBtnClicked ? mCurSelectedBaseNode : NULL;
}

/// 重置结点状态
void GuiManager::reset(void)
{
    //std::lock_guard<std::mutex> lock(mNodeMutex);

    std::map<int,GuiBaseNode*>::iterator iter = mBaseNodes.begin();
    for(;iter != mBaseNodes.end();++iter)
    {
        (*iter).second->reset();
    }
}
